 /*
 *
 * Copyright (c) 2009, dana koch
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */
package btplay;

import java.lang.*;
import java.io.*;
import java.util.*;

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.device.api.media.control.AudioPathControl;

import javax.microedition.media.control.VolumeControl;
import javax.microedition.media.Control;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.io.*;
import javax.microedition.io.file.*;


final class PlayerController 
{
   private Player player;
    
   private boolean inited;
   private String duration;
    
   PlayerController()
   {
      this.player = null;
      this.inited = false;
      this.duration = "";
   }
    
   public void init(String url, PlayerListener listener)
   {
      try
      {
         player = null;
         player = javax.microedition.media.Manager.createPlayer(
            "file://" + url);
              
         player.addPlayerListener(listener);
      }
      catch(Exception e)
      {
         PlayerController.alert("init: " + e.toString()); System.exit(1);
      }
       
      this.inited = true;
   }
    
   public boolean inited()
   {
      return inited;
   }

   public void ready()
   {        
      if(player.getState() == javax.microedition.media.Player.UNREALIZED)
         realize();
       
      if(player.getState() == javax.microedition.media.Player.REALIZED)
         prefetch();
          
      if(player.getState() == javax.microedition.media.Player.PREFETCHED)     
         return; // we're done
   }
    
   public void realize()
   {
      try
      {
         player.realize();
      }
      catch(Exception e)
      {
         PlayerController.alert("realize: " + e.toString()); System.exit(1);
      }
       
      setBtAudioPath();
      setVolume(100);
   }
    
   public void prefetch()
   {
      try
      {
         player.prefetch();
      }
      catch(Exception e)
      {
         PlayerController.alert("prefetch: " + e.toString()); System.exit(1);
      }  
   }   
    

   public void play()
   {
      try
      {
         player.start();
      }
      catch(Exception e)
      {
         PlayerController.alert("play: " + e.toString()); 
      }
   }    
    
   public void pause()
   {
      try
      {
         player.stop();
      }
      catch(Exception e)
      {
         PlayerController.alert("play: " + e.toString());
      }
   }
   
   public void close()
   {
      deallocate();
      player.close();
      
      this.inited = false;
      this.duration = "";
   }
   
   public void deallocate()
   {
      try
      {
         player.deallocate();
      }
      catch(Exception e)
      {
         PlayerController.alert("deallocate: " + e.toString());
      }
   }

    
   public static void alert(String message)
   {
       System.err.println(">>> " + message);
       Dialog.alert(message);
   }
   
   public void setBtAudioPath()
   {
      AudioPathControl c = null;
      
      try
      {
         c = (AudioPathControl) player.getControl(
         "net.rim.device.api.media.control.AudioPathControl");
      }
      catch(Exception e)
      {
         PlayerController.alert("setBtAudioPath: getControl: " + e.toString());
         return;
      }
      
      try
      {
         c.setAudioPath(AudioPathControl.AUDIO_PATH_BLUETOOTH);
      }
      catch(Exception e)
      {
         //PlayerController.alert("setBtAudioPath: setAudioPath: " + e.toString());
         PlayerController.alert("Bluetooth headset audio unavailable. Routing audio"
            + "to speaker.");
         setVolume(50);
      }
   }
   
   public int getVolume()
   {
      VolumeControl c = null;
      int volume = 0;
      
      try
      {
         c = (VolumeControl) player.getControl(
      "javax.microedition.media.control.VolumeControl");
      }
      catch(Exception e)
      {
         PlayerController.alert("getVolume: getControl: " + e.toString());
         return -1;
      }
      
      try
      {
         volume = c.getLevel();
      }
      catch(Exception e)
      {
         PlayerController.alert("getVolume: getLevel: " + e.toString());
      }
      
      return volume;
   }
   
   public int setVolume(int volume)
   {
      VolumeControl c = null;
      int ret = 0;
      
      try
      {
         c = (VolumeControl) player.getControl(
     "javax.microedition.media.control.VolumeControl");
      }
      catch(Exception e)
      {
         PlayerController.alert("getVolume: getControl: " + e.toString());
         return -1;
      }
      
      try
      {
         ret = c.setLevel(volume);
      }
      catch(Exception e)
      {
         PlayerController.alert("setBtAudioPath: : " + e.toString());
      }
      
      return ret;
   }
   
   public long getMediaTime()
   {
      long ret = 0;
      
      try 
      {
         ret = player.getMediaTime();
      }
      catch(Exception e) 
      {
         PlayerController.alert("getMediaTime: " + e.toString()); 
      }
      
      return ret; 
   }
   
   public String duration()
   {
      long duration_microseconds = 0;
      int time_seconds = 0;
      int hours = 0;
      int minutes = 0;
      int seconds = 0;
      
      if(!duration.equals(""))
         return duration;
         
      try 
      {
         duration_microseconds = player.getDuration();
      }
      catch(Exception e) 
      {
         PlayerController.alert("getMediaTime: " + e.toString());
         duration = "0";
         return "0";
      }
      
      time_seconds = (int) 
   Math.floor((float)duration_microseconds / (float)1000000 + 0.5);
      
      hours = time_seconds / (60 * 60);
      minutes = (time_seconds - hours * 60 * 60) / 60;
      seconds = time_seconds - hours * 60 * 60 - minutes * 60;
      
      duration = PlayerController.formatTime(hours, minutes, seconds);
      return duration;
   }
   
   public void skipForward(int seconds)
   {
      try
      {
         long currentTime = player.getMediaTime();
         long nextTime = player.getMediaTime() + seconds * 1000000;
         long setTime = player.setMediaTime(nextTime);
      }
      catch(Exception e)
      {
         PlayerController.alert("skipForward: : " + e.toString());
      }
   }
   
   public void skipBackward(int seconds)
   {
      try
      {
         player.setMediaTime(player.getMediaTime() - seconds * 1000000);
      }
      catch(Exception e)
      {
         PlayerController.alert("skipForward: : " + e.toString());
      }
   }

   public static String formatTime(int hours, int minutes, int seconds)
   {
      String ret = Integer.toString(hours) + ":";
      
      if(minutes < 10)
         ret += "0" + Integer.toString(minutes) + ":";
      else
         ret += Integer.toString(minutes) + ":";
         
      if(seconds < 10)
         ret += "0" + Integer.toString(seconds);
      else
         ret += Integer.toString(seconds);
         
      return ret;
   }
}


